import { Context } from "koa";
import * as log4js from "log4js";
import path from "path";

log4js.configure({
    appenders: {
        console: { type: "console" },
        error: { type: "file", filename: path.resolve(__dirname, "../../log/error.log") },
        http: {
            type: "dateFile",
            filename: path.resolve(__dirname, "../../log/http"),
            pattern: "-yyyy-MM-dd.log", // 日志文件命名规则，eg：http-2024-10-21.log
            alwaysIncludePattern: true // 始终以该规则命名
        },
        mysql: {
            type: "dateFile",
            filename: path.resolve(__dirname, "../../log/msyql"),
            pattern: "-yyyy-MM-dd.log",
            alwaysIncludePattern: true
        }
    },
    categories: {
        // 默认的记录器只要在控制台打印就好，开发环境 logger.debug 级别就可打印，生产环境 logger.info 才可打印
        default: { appenders: ["console"], level: process.env.NODE_ENV !== "development" ? "info" : "debug" },
        // 专门记录所有错误
        error: { appenders: ["console", "error"], level: "error" },
        // 专门记录 http 服务日志
        http: { appenders: ["http"], level: "info" },
        mysql: { appenders: ["mysql"], level: "error" }
    }
});

export const logger = log4js.getLogger();
export const errorLogger = log4js.getLogger("error");
// http 日志记录器
export const httpLogger = log4js.getLogger("http");
export const mysqlLogger = log4js.getLogger("mysql");

// API请求、响应日志记录中间件
export const httpLoggerMiddleware = async (ctx: Context, next) => {
    const { method, url } = ctx;
    const { body } = ctx.request;

    // 请求发生错误，同时记录错误在 http.log 和 error.log
    const httpErrorLog = (status, message, error: any = "") => {
        errorLogger.error("----------- http 错误 ----------");
        errorLogger.error(method, url, status, message, body);
        errorLogger.error(error);
        httpLogger.error(method, url, status, message, body);
        httpLogger.error(error);
    };

    // 请求成功，记录日志在 http.log，并且为了开发方便，也在控制台输出打印
    const httpResponseSuccessLog = (status, message) => {
        logger.debug("<--", method, url, status, message);
        httpLogger.info("<--", method, url, status, message);
    };

    // 开发环境控制台打印一下请求信息
    logger.debug("-->", method, url);

    httpLogger.info("-->", method, url);

    try {
        await next();
        const { status, message } = ctx.response;
        if (status >= 400) {
            httpErrorLog(status, message);
        } else {
            httpResponseSuccessLog(status, message);
        }
    } catch (error) {
        httpErrorLog(ctx.response.status, ctx.response.message, error);
    }
};
